﻿using System;
using System.Drawing;
using System.Net.Http;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    /// <summary>
    /// 异步地显式页面长度
    /// </summary>
    public partial class FormDisplayLength : Form
    {
        Label label;
        Button button;

        public FormDisplayLength()
        {
            InitializeComponent();

            label = new Label
            {
                Location = new Point(10, 21),
                Text = "Length"
            };

            button = new Button
            {
                Location = new Point(10, 50),
                Text = "Click"
            };

            button.Click += DisplayWebSiteLength;

            AutoSize = true;
            Controls.Add(label);
            Controls.Add(button);
        }

        async void DisplayWebSiteLength(object sender, EventArgs e)
        {
            label.Text = "Fetching...";
            using (HttpClient client = new HttpClient())
            {
                string text = await client.GetStringAsync("https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/");     // 编译器生成的代码将包含一个状态机，并且在 GetStringAsync 的返回值上附加一个后续操作，所有这一切都是实现细节。
                label.Text = text.Length.ToString();
            }
        }
        // await 的主要目的是在等待耗时操作完成时避免阻塞。
        // 巧妙之处在于，方法在执行到await表达式时就返回了。
        // 在此之前，它与其他事件处理程序一样，都是在UI线程同步执行的。如果在第一行加断点进行调试，你会发现堆栈跟踪显示按钮正在触发Click事件，包括Button.OnClick方法。
        // 到达await后，代码将检查其结果是否存在。如果不存在（几乎总是如此），会安排一个在Web操作完成时将要执行的后续操作（continuation）。
        // 在本例中，后续操作将执行剩下的代码，跳到await表达式的末尾，并如你所愿地回到UI线程，以便在UI上进行操作。

    }
}
